package com.didi.gulimall.ware.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.didi.gulimall.common.constant.WareConstant;
import com.didi.gulimall.common.exception.NoStockException;
import com.didi.gulimall.common.to.OrderBackVo;
import com.didi.gulimall.common.to.OrderSuccessVo;
import com.didi.gulimall.common.to.OrderTo;
import com.didi.gulimall.common.utils.LogUtils;
import com.didi.gulimall.common.utils.PageUtils;
import com.didi.gulimall.common.utils.Query;
import com.didi.gulimall.common.utils.R;
import com.didi.gulimall.common.vo.OrderItemVo;
import com.didi.gulimall.ware.dao.WareOrderTaskDao;
import com.didi.gulimall.ware.entity.WareOrderTaskDetailEntity;
import com.didi.gulimall.ware.entity.WareOrderTaskEntity;
import com.didi.gulimall.ware.service.WareOrderTaskDetailService;
import com.didi.gulimall.ware.service.WareOrderTaskService;
import com.didi.gulimall.ware.service.WareSkuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 10626
 */
@Slf4j
@Service("wareOrderTaskService")
public class WareOrderTaskServiceImpl extends ServiceImpl<WareOrderTaskDao, WareOrderTaskEntity> implements WareOrderTaskService {
    @Autowired
    private WareSkuService wareSkuService;

    @Autowired
    private WareOrderTaskDetailService wareOrderTaskDetailService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<WareOrderTaskEntity> page = this.page(
                new Query<WareOrderTaskEntity>().getPage(params),
                new QueryWrapper<WareOrderTaskEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * // TODO  自旋解锁库存
     *
     * @param orderVo
     * @return
     */
    @Override
    public R deductionInventory(OrderTo orderVo) {
        WareOrderTaskEntity wareOrder = new WareOrderTaskEntity();
        wareOrder.setConsignee(orderVo.getReceiverPhone());
        wareOrder.setDeliveryAddress(orderVo.getReceiverDetailAddress());
        wareOrder.setOrderComment(orderVo.getNote());
        wareOrder.setTaskStatus(WareConstant.OrderWorkOrderStatus.CREATED.getCode());
        wareOrder.setLookStatus(WareConstant.LOCKING);
        wareOrder.setOrderId(orderVo.getId());
        wareOrder.setCreateTime(new Date());
        wareOrder.setOrderBody(WareConstant.OrderWorkOrderStatus.CREATED.getMsg());
        List<OrderItemVo> orderItemVos = orderVo.getItemVos();
        try {
            List<WareOrderTaskDetailEntity> collect = orderItemVos.stream().map(orderItemVo -> {
                WareOrderTaskDetailEntity wareOrderTaskDetail = new WareOrderTaskDetailEntity();
                wareOrderTaskDetail.setSkuNum(orderItemVo.getCount());
                wareOrderTaskDetail.setSkuId(orderItemVo.getSkuId());
                wareOrderTaskDetail.setSkuName(orderItemVo.getSkuTitle());
                wareOrderTaskDetail.setOrderSn(orderVo.getOrderSn());
                wareOrderTaskDetail.setTaskId(wareOrder.getId());
                List<Long> wareId = wareSkuService.listWareIdHasSkuStock(orderItemVo.getSkuId(), orderItemVo.getCount());
                if (CollectionUtils.isEmpty(wareId)) {
                    throw new NoStockException(orderItemVo.getSkuId());
                }
                wareOrderTaskDetail.setWareIds(wareId);
                return wareOrderTaskDetail;
            }).collect(Collectors.toList());
            Map<Long, List<WareOrderTaskDetailEntity>> map = lockInventory(wareOrder, collect);
            return R.ok().put("data", map);
        } catch (NoStockException e) {
            log.error(LogUtils.getStackTraceInfo(e));
            return R.error(e.getMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Map<Long, List<WareOrderTaskDetailEntity>> lockInventory(WareOrderTaskEntity wareOrder, List<WareOrderTaskDetailEntity> collect) {
        Map<Long, List<WareOrderTaskDetailEntity>> map = new HashMap<>();
        for (WareOrderTaskDetailEntity wareOrderTaskDetailEntity : collect) {
            List<Long> wareIds = wareOrderTaskDetailEntity.getWareIds();
            boolean isflg = false;
            for (Long wareId : wareIds) {
                Long flg = wareSkuService.lockSkuStock(wareOrderTaskDetailEntity.getSkuNum(), wareOrderTaskDetailEntity.getSkuId(), wareId);
                if (flg == 1L) {
                    wareOrderTaskDetailEntity.setWareId(wareId);
                    isflg = true;
                    List<WareOrderTaskDetailEntity> orderItem = map.get(wareId);
                    if (CollectionUtils.isEmpty(orderItem)) {
                        // 没有
                        String orderSn = IdWorker.getTimeId();
                        wareOrder.setOrderSn(orderSn);
                        wareOrderTaskDetailEntity.setOrderSn(orderSn);
                        List<WareOrderTaskDetailEntity> wareOrderItems = new ArrayList<>();
                        WareOrderTaskDetailEntity wareOrderItem = new WareOrderTaskDetailEntity();
                        wareOrderItem.setSkuId(wareOrderTaskDetailEntity.getSkuId());
                        wareOrderItem.setSkuNum(wareOrderTaskDetailEntity.getSkuNum());
                        wareOrderItem.setOrderSn(orderSn);
                        wareOrderItems.add(wareOrderItem);
                        map.put(wareId, wareOrderItems);
                        baseMapper.insert(wareOrder);
                    } else {
                        //有
                        WareOrderTaskDetailEntity orderTaskDetailEntity = orderItem.get(0);
                        String orderSn = orderTaskDetailEntity.getOrderSn();
                        wareOrderTaskDetailEntity.setOrderSn(orderSn);
                        WareOrderTaskDetailEntity wareOrderItem = new WareOrderTaskDetailEntity();
                        wareOrderItem.setSkuId(wareOrderTaskDetailEntity.getSkuId());
                        wareOrderItem.setSkuNum(wareOrderTaskDetailEntity.getSkuNum());
                        wareOrderItem.setOrderSn(orderSn);
                        orderItem.add(wareOrderItem);
                    }
                    break;
                }
            }
            if (!isflg) {
                // 当前商品没有锁定库存成功
                throw new NoStockException(wareOrderTaskDetailEntity.getSkuId());
            }
        }
        wareOrderTaskDetailService.saveBatch(collect);
        return map;
    }

    @Override
    public WareOrderTaskEntity getIdByOrderSn(String orderSn) {
        return baseMapper.selectOne(new QueryWrapper<WareOrderTaskEntity>().eq("order_sn", orderSn));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderBack(OrderBackVo orderBackVo) {
        WareOrderTaskEntity wareOrderTaskEntity = getIdByOrderSn(orderBackVo.getOrderSn());
        if (wareOrderTaskEntity == null || wareOrderTaskEntity.getLookStatus().equals(WareConstant.UNLOCK)) {
            return;
        }
        List<WareOrderTaskDetailEntity> wareOrderTaskDetailEntityList = wareOrderTaskDetailService.list(new QueryWrapper<WareOrderTaskDetailEntity>().eq("order_sn", wareOrderTaskEntity.getOrderSn()));

        for (WareOrderTaskDetailEntity wareOrderTaskDetailEntity : wareOrderTaskDetailEntityList) {
            wareSkuService.unLook(wareOrderTaskDetailEntity.getSkuId(), wareOrderTaskDetailEntity.getWareId(), wareOrderTaskDetailEntity.getSkuNum(), orderBackVo.getHasStock());
        }
        wareOrderTaskEntity.setLookStatus(WareConstant.UNLOCK);
        wareOrderTaskEntity.setUnlockTime(new Date());
        wareOrderTaskEntity.setTaskStatus(WareConstant.OrderWorkOrderStatus.CANCELLED.getCode());
        baseMapper.updateById(wareOrderTaskEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paysuccessDeductionInventory(OrderSuccessVo orderSuccessVo) {
        WareOrderTaskEntity wareOrderTaskEntity = getIdByOrderSn(orderSuccessVo.getOrderSn());
        if (wareOrderTaskEntity == null || wareOrderTaskEntity.getTaskStatus().equals(WareConstant.OrderWorkOrderStatus.STOCKING.getCode())) {
            return;
        }
        List<WareOrderTaskDetailEntity> wareOrderTaskDetailEntityList = wareOrderTaskDetailService.list(new QueryWrapper<WareOrderTaskDetailEntity>().eq("order_sn", wareOrderTaskEntity.getOrderSn()));
        for (WareOrderTaskDetailEntity wareOrderTaskDetailEntity : wareOrderTaskDetailEntityList) {
            wareSkuService.deductionInventory(wareOrderTaskDetailEntity.getSkuId(), wareOrderTaskDetailEntity.getWareId(), wareOrderTaskDetailEntity.getSkuNum());
        }
        wareOrderTaskEntity.setTaskStatus(WareConstant.OrderWorkOrderStatus.STOCKING.getCode());
        baseMapper.updateById(wareOrderTaskEntity);
    }
}